package br.com.felix.fwt.ui.css;

import java.io.Serializable;

import br.com.felix.fwt.ui.Image;

/**
 * Utility class to help customizing the appearence of the user interface components.
 * It is the framework's way of using Cascading Style Sheets.
 * All properties are optional, and only the defined properties will be generated in the output.
 */
public class Style implements Serializable, Cloneable{
	
	private static final long serialVersionUID = -7554856995315016253L;
	
	/** The height. */
	public Size left,top,bottom,right,width,height;
	
	/** The background image. */
	public Image backgroundImage;
	
	/** The position. */
	public Position position;
	
	/** The font family. */
	public String fontFamily;
	
	/** The font size. */
	public FontSize fontSize;
	
	/** The background color. */
	public Color backgroundColor;
	
	/** The text align. */
	public Align textAlign;
	
	/** The margin. */
	public int[] margin;
	
	/** The padding. */
	public int[] padding;
	
	/** The float. */
	public br.com.felix.fwt.ui.css.CssFloat floatTo;
	
	/** The display. */
	public Display display;
	
	/** The cursor. */
	public Cursor cursor;
	
	/** The border. */
	public Border border;
	
	/** The name of the style. It is optional.
	 * Use this property if you want to (re)define a CSS class.
	 * For example: H, TABLE, .myinput, .mytable, mybutton
	 *  */
	public String name;

	/**
	 * The font color.
	 * */
	public Color color;
	
	/**
	 * Defines how content is rendered when clipping occurs.
	 * */
	public Overflow overflow;
	
	/**
	 * Background image.
	 * 
	 * @param img the img
	 * 
	 * @return this instance
	 */
	public Style backgroundImage(Image img){
		this.backgroundImage = img;
		return this;
	}
	
	/**
	 * Left.
	 * 
	 * @param x the x
	 * 
	 * @return this instance
	 */
	public Style left(Size x){
		this.left = x;
		return this;
	}
	
	/**
	 * Top.
	 * 
	 * @param y the y
	 * 
	 * @return this instance
	 */
	public Style top(Size y){
		this.top = y;
		return this;
	}
	
	
	/**
	 * Bottom.
	 * 
	 * @param bottom the bottom
	 * 
	 * @return this instance
	 */
	public Style bottom(Size bottom){
		this.bottom = bottom;
		return this;
	}
	
	/**
	 * Width.
	 * 
	 * @param width the width
	 * 
	 * @return this instance
	 */
	public Style width(Size width){
		this.width = width;
		return this;
	}
	
	/**
	 * Height.
	 * 
	 * @param height the height
	 * 
	 * @return this instance
	 */
	public Style height(Size height){
		this.height= height;
		return this;
	}
	
	
	/**
	 * Right.
	 * 
	 * @param right the right
	 * 
	 * @return this instance
	 */
	public Style right(Size right){
		this.right = right;
		return this;
	}
	
	/**
	 * Left.
	 * 
	 * @param x the x
	 * 
	 * @return this instance
	 */
	public Style left(int x){
		this.left = new PixelSize(x);
		return this;
	}
	
	/**
	 * Top.
	 * 
	 * @param y the y
	 * 
	 * @return this instance
	 */
	public Style top(int y){
		this.top = new PixelSize(y);
		return this;
	}
	
	/**
	 * Bottom.
	 * 
	 * @param bottom the bottom
	 * 
	 * @return this instance
	 */
	public Style bottom(int bottom){
		this.bottom = new PixelSize(bottom);
		return this;
	}
	
	/**
	 * Width.
	 * 
	 * @param width the width
	 * 
	 * @return this instance
	 */
	public Style width(int width){
		this.width = new PixelSize(width);
		return this;
	}
	
	/**
	 * Height.
	 * 
	 * @param height the height
	 * 
	 * @return this instance
	 */
	public Style height(int height){
		this.height= new PixelSize(height);
		return this;
	}
	
	
	/**
	 * Right.
	 * 
	 * @param right the right
	 * 
	 * @return this instance
	 */
	public Style right(int right){
		this.right = new PixelSize(right);
		return this;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString(){
		StringBuilder strb = new StringBuilder();
		strb.append(" style=\"");
		writeStyle(strb);
		strb.append("\"");
		return strb.toString();
	}
	
	
	/**
	 * Declaration.
	 * 
	 * @return the string
	 */
	public String declaration(){
		StringBuilder strb = new StringBuilder();
		strb.append(name).append("{");
		writeStyle(strb);
		strb.append("}");
		return strb.toString();
	}
	
	/**
	 * Generates the CSS output.
	 * 
	 * @param strb the StringBuilder where the output will be generated.
	 */
	private void writeStyle(StringBuilder strb){
		if(overflow!=null)strb.append("overflow:").append(overflow).append(";");
		if(left!=null)strb.append("left:").append(left).append(";");
		if(right!=null)strb.append("right:").append(right).append(";");
		if(top!=null)strb.append("top:").append(top).append(";");
		if(bottom!=null)strb.append("bottom:").append(bottom).append(";");
		if(width!=null)strb.append("width:").append(width).append(";");
		if(height!=null)strb.append("height:").append(height).append(";");
		if(color!=null)strb.append("color: ").append(color).append(";");
		if(fontFamily!=null)strb.append("font-family:").append(fontFamily).append(";");
		if(fontSize!=null)strb.append("font-size:").append(fontSize).append(";");
		if(textAlign!=null)strb.append("text-align:").append(textAlign).append(";");
		if(border!=null)strb.append(border.toString());
		if(margin!=null){
			strb.append("margin:");
			for(int i=0;i<margin.length;i++)strb.append(margin[i]).append("px ");
			strb.append(";");
		}
		if(padding!=null){
			strb.append("padding:");
			for(int i=0;i<padding.length;i++)strb.append(padding[i]).append("px ");
			strb.append(";");
		}
		if(display!=null)strb.append("display:").append(display).append(";");
		if(cursor!=null)strb.append("cursor:").append(cursor).append(";");
		if(position!=null)strb.append("position:").append(position).append(";");
		if(backgroundImage!=null)strb.append("background-image: url('").append(backgroundImage.getValue()).append("');");
		if(backgroundColor!=null)strb.append("background-color:").append(backgroundColor.toString()).append(";");
		if(floatTo!=null)strb.append("float:").append(floatTo).append(";");
	}

	/**
	 * Position.
	 * 
	 * @param position the position
	 * 
	 * @return this instance
	 */
	public Style position(Position position) {
		this.position = position;
		return this;
	}

	/**
	 * Background color.
	 * 
	 * @param color the color
	 * 
	 * @return this instance
	 */
	public Style backgroundColor(Color color) {
		this.backgroundColor = color;
		return this;
	}
	
	/**
	 * Text align.
	 * 
	 * @param align the align
	 * 
	 * @return this instance
	 */
	public Style textAlign(Align align) {
		this.textAlign = align;
		return this;
	}

	/**
	 * top, right, bottom, left.
	 * 
	 * @param margin the margin
	 * 
	 * @return this instance
	 */
	public Style margin(int ... margin) {
		this.margin = margin;
		return this;
	}
	
	
	/**
	 * top, right, bottom, left.
	 * 
	 * @param padding the padding
	 * 
	 * @return this instance
	 */
	public Style padding(int ... padding) {
		this.padding = padding;
		return this;
	}
	
	/**
	 * Font size.
	 * 
	 * @param f the f
	 * 
	 * @return this instance
	 */
	public Style fontSize(FontSize f){
		this.fontSize = f;
		return this;
	}

	/**
	 * Float to.
	 * 
	 * @param f the f
	 * 
	 * @return this instance
	 */
	public Style floatTo(CssFloat f) {
		this.floatTo = f;
		return this;
	}
	
	
	/**
	 * Sets the border
	 * */
	public Style border(Border border){
		this.border = border;
		return this;
	}
	
	/**
	 * Reverse engineer a CSS style definition and obtain the value of a property (just a simple substring).
	 * 
	 * @param property the property you wish to know the value.
	 * @param style the CSS style you want to inspect for a property.
	 * 
	 * @return the value of the informed property.
	 */
	public static String valueOf(String property, String style){
		int indexA = style.indexOf(property);
		int indexA2 = style.indexOf(":",indexA)+1;
		int indexB = style.indexOf(";",indexA);
		return style.substring(indexA2, indexB).trim();
	}

	/**
	 * Display.
	 * 
	 * @param d the d
	 * 
	 * @return this instance
	 */
	public Style display(Display d) {
		this.display = d;
		return this;
	}

	public Style cursor(Cursor cursor) {
		this.cursor = cursor;
		return this;
	}

	public Style color(Color color) {
		this.color = color;
		return this;
	}
	
	@Override
	public Object clone() {
		Style clone = new Style();
		clone.backgroundColor = backgroundColor;
		clone.backgroundImage = backgroundImage;
		clone.border = border;
		clone.bottom = bottom;
		clone.color = color;
		clone.cursor = cursor;
		clone.display = display;
		clone.floatTo = floatTo;
		clone.fontFamily = fontFamily;
		clone.fontSize = fontSize;
		clone.height = height;
		clone.left = left;
		clone.margin = margin;
		clone.name = name;
		clone.overflow = overflow;
		clone.padding = padding;
		clone.position = position;
		clone.right = right;
		clone.textAlign = textAlign;
		clone.top = top;
		clone.width = width;
		return clone;
	}

}
